home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 28
/
Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso
/
Aminet
/
dev
/
c
/
dice-3.16.lha
/
examples
/
Visual
/
VCommon
/
vmenu.c
< prev
Wrap
C/C++ Source or Header
|
1998-09-27
|
13KB
|
427 lines
#include "project.h"
#ifdef PROJECT_VOPTS
#include "vopts.h"
#endif
#ifdef PROJECT_VMAKE
#include "vmake.h"
#endif
#include <proto/gadtools.h>
Prototype void enable_menu(void);
Prototype struct Menu *create_menus(struct NewMenu *menulist);
Prototype int layout_menus(struct Menu *menus);
Prototype void free_menus(struct Menu *menus);
Prototype void ghost_menus(void);
Prototype void unghost_menus(void);
/***********************************************************************************
* Procedure: enable_menu
* Synopsis: enable_menu();
* Purpose: Attach any system defined menus to the current window.
***********************************************************************************/
void enable_menu()
{
int i, level, newlev, count[4];
struct NewMenu *newmenu;
if (global.window == NULL) return;
/* Let us go through and validate the menu they have constructed */
level = 0;
newmenu = global.menuitem;
for (i = 0; i < MAX_MENU; i++)
{
newlev = newmenu[i].nm_Type;
if (newlev > level)
{
level++;
/* Make sure we are going down only one level */
if (newmenu[i].nm_Type != level || level > MENU_SUB) return;
count[level] = 0; /* Initialize our count */
}
else if (newlev == level)
{
/* Make sure we don't have two TITLES in a row */
if (level == MENU_MENU) return;
count[level]++;
}
else
{
/* We are going up a level. Validate the counts on the way up */
if (newlev < MENU_END) return;
while (level > newlev)
{
if (count[level] >= "!\x20\x40\x20"[level])
return;
else
level--;
}
/* When we hit the end of the menus, break */
if (level == 0) break;
count[level]++;
}
}
/* Lastly ensure that they had an END marker */
if (level) return;
if (!(global.menu = create_menus(newmenu)))
return;
if (!layout_menus(global.menu))
return;
SetMenuStrip(global.window, global.menu);
}
/***********************************************************************************
* Procedure: create_menus
* Synopsis: Menu = create_menus(NewMenu);
* Purpose: Create the appropriate menu structures for a given NewMenu list
***********************************************************************************/
struct Menu *create_menus(struct NewMenu *menulist
)
{
int i;
struct Menu *retmenu;
struct XMenu *thismenu;
struct XItem *thisitem;
static struct Image sep_image = {5, 1, 1000, 2,0, NULL, 0,0, NULL};
if (GadToolsBase != NULL)
{
struct TagItem taglist[2];
taglist[0].ti_Tag = GTMN_FrontPen;
taglist[0].ti_Data = 0;
taglist[1].ti_Tag = TAG_DONE;
return(CreateMenusA(menulist, taglist));
}
/* We don't have GadTools around to do the work for us, so just create the */
/* Menu structures directly. */
retmenu = NULL; /* Default to giving them NOTHING */
for (i = 0; i < MAX_MENU; i++)
{
switch (menulist[i].nm_Type)
{
case NM_TITLE:
{
struct XMenu *newmenu;
newmenu = (struct XMenu *)get_mem(sizeof(struct XMenu));
if (newmenu == NULL)
{
free_menus(retmenu);
return(NULL);
}
/* Link the menu structure onto the list of other menus */
if (retmenu == NULL)
retmenu = &newmenu->menu;
else
thismenu->menu.NextMenu = &newmenu->menu;
thismenu = newmenu;
}
thismenu->menu.Flags = MENUENABLED;
thismenu->menu.MenuName = (BYTE *)menulist[i].nm_Label;
thismenu->userdata = menulist[i].nm_UserData;
thismenu->image = sep_image;
break;
case NM_ITEM:
if (thismenu == NULL) return(NULL);
{
struct XItem *newitem;
newitem = (struct XItem *)get_mem(sizeof(struct XItem));
if (newitem == NULL)
{
free_menus(retmenu);
return(NULL);
}
if (thismenu->menu.FirstItem == NULL)
thismenu->menu.FirstItem = &newitem->item;
else
thisitem->item.NextItem = &newitem->item;
thisitem = newitem;
}
if (menulist[i].nm_Label == NM_BARLABEL)
{
thisitem->item.Flags = 0;
thisitem->item.ItemFill = &thismenu->image;
}
else
{
/* fill in the intuitext with some reasonable defaults */
thisitem->itext.FrontPen = 0;
thisitem->itext.DrawMode = JAM1;
thisitem->itext.LeftEdge = 5;
thisitem->itext.TopEdge = 1;
thisitem->itext.ITextFont = &global.ri.TextAttr;
thisitem->itext.IText = menulist[i].nm_Label;
thisitem->item.Flags = ITEMTEXT|ITEMENABLED|HIGHCOMP;
thisitem->item.ItemFill = (APTR)&thisitem->itext;
if (menulist[i].nm_CommKey)
{
thisitem->item.Command = *menulist[i].nm_CommKey;
thisitem->item.Flags |= COMMSEQ;
}
}
thisitem->userdata = menulist[i].nm_UserData;
break;
case NM_END:
return(retmenu);
}
}
return(retmenu);
}
/***********************************************************************************
* Procedure: layout_menus
* Synopsis: rc = layout_menus(Menu);
* Purpose: Lays out a menu given the current global information
***********************************************************************************/
int layout_menus(struct Menu *menus)
{
struct XMenu *menu;
struct XItem *item;
int xpos;
if (GadToolsBase != NULL)
{
struct VisualInfo *vi;
struct TagItem taglist;
int rc;
taglist.ti_Tag = TAG_DONE;
rc = 0;
if ((vi = GetVisualInfoA(global.window->WScreen, &taglist)))
{
rc = LayoutMenusA(global.menu, vi, &taglist);
FreeVisualInfo(vi);
}
return(rc);
}
xpos = VBAR;
for (menu = (struct XMenu *)menus; menu;
menu = (struct XMenu *)menu->menu.NextMenu)
{
int width, ypos;
/* set the x position of the menu to the next available position.
* Set the menu width based on the size of the text.
*/
menu->menu.LeftEdge = xpos;
menu->menu.Width = text_width(menu->menu.MenuName) + DVBAR;
/* set the initial item y-position to just below the title bar */
ypos = 0;
/* walk through the list of items for the first pass. The object
* is to find the width of the largest item. We will also set
* the y-position of each item on this pass.
*/
width = menu->menu.Width; /* make items at least as big as menu */
for (item = (struct XItem *)menu->menu.FirstItem;
item;
item = (struct XItem *)item->item.NextItem)
{
int iwidth;
/* set the y-position of the item to the next available. Also,
* put the item just to the left of the menu. You can make
* this number zero if you prefer.
*/
item->item.TopEdge = ypos;
item->item.LeftEdge = -VBAR;
/* if it's a text item, see how big it is. */
if (item->item.Flags & ITEMTEXT)
{
struct IntuiText *itext;
itext = (struct IntuiText *)item->item.ItemFill;
/* the height is just the font height + 2. The width is
* based on the string pixel width.
*/
item->item.Height = global.ri.FontSize + 2;
iwidth = text_width(itext->IText) + 10;
/* i